package blackjack.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import blackjack.client.appletVisualAndLogic.CardDeck;

class ClientSession extends Thread {
	@SuppressWarnings("unchecked")
	ArrayList cards = new ArrayList();

	private Socket socket;

	private CardDeck playerCards;
	private OutboundMessages outQueue;
	private ActiveSessions activeSessions;

	private BufferedReader netIn;
	private PrintWriter netOut;

	private int allPoints = 0;
	private int ready = 0;

	public ClientSession(Socket s, OutboundMessages out, ActiveSessions as) throws IOException {
		playerCards = new CardDeck();
		socket = s;
		outQueue = out;
		activeSessions = as;
		netIn = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		netOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
		start();
	}

	@SuppressWarnings("unchecked")
	public void run() {
		try {
			String name = netIn.readLine(); // blocked - ootab kliendi nime
			super.setName(name); // anname endale nime
			// registreerime end kui aktiivse
			activeSessions.addSession(this);// jutustaja
			String str = name + " tuli sisse...";
			outQueue.addMessage(str); // teatame sellest koigile

			try {
				/*GETTING IMPRTANT PLAYER INFO IP,NAME,MACHINE NAME, DATE PLAYED. AND SAVING IT TO FILE*/
				Date now = new Date();
				DateFormat df = DateFormat.getDateTimeInstance();
				InetAddress ip =InetAddress.getLocalHost();//getting ip
				String computername=InetAddress.getLocalHost().getHostName();//getting Machine name
				String date = df.format(now);

				BufferedWriter netOut = new BufferedWriter(new FileWriter("logifail.csv", true));
				netOut.write("Playername: " + name + ", IP adress: " + ip + ", MachineName: " + computername
						+ ", Date " + date + ", played THE GAME.");
				netOut.write("\n");
				netOut.close();
			} catch (IOException e) {
				System.out.println("File do not exist!!");
			}

			while (true) { // Jutustaja elutsukli pohiosa *********************
				if(activeSessions.g != 0 && (activeSessions.getAmountOfPlayers() == 0 || activeSessions.getAmountOfPlayers() == 1))
					beginning();{

					}
					str = netIn.readLine(); // blocked...
					if( activeSessions.getAmountOfPlayers() < 2){beginning();}
					if( activeSessions.getAmountOfPlayers() == 0){beginning();}
					if( activeSessions.getAmountOfPlayers() == 1){beginning();}
					if (str == null) {
						continue; 					// tuli EOF
					}
					if (str.equalsIgnoreCase("QUIT")) {//donT work
						break;
					}
					if(str.equals("getCard")){//POINTS<30

						if(activeSessions.getAmountOfPlayers() < 2 &&  activeSessions.kokku == 0){this.sendMessage("waiting For Payers. Current player number is " + activeSessions.getAmountOfPlayers());continue;}
						if(activeSessions.g == 0){
							activeSessions.kokku = activeSessions.getAmountOfPlayers();
							activeSessions.g++;outQueue.addMessage("k "+activeSessions.kokku + " kokku");
						}
						String card;
						card = this.playerCards.getCard();
						this.cards.add(card);
						this.allPoints += playerCards.CardStringtoInt(card);
						this.sendMessage(card);
						str = card + " (FOR CHECKING CARD AND TEXT)";//lihtsaks kontrollimiseks
					}

					if(activeSessions.g != 0 && (activeSessions.getAmountOfPlayers() == 0 || activeSessions.getAmountOfPlayers() == 1))beginning();
					if(str != null && str.equals("enough")){
						Iterator t = activeSessions.iterator();
						while (t.hasNext()) {
							ClientSession cs = (ClientSession) t.next();
							if(cs.equals(this))continue;
							cs.sendMessage("enough");
						}
						this.ready++;
					}

					// searches best result
					if(this.checkGameOver() == true){
						int max = 0;
						String winnerName = "";
						synchronized (activeSessions) {
							Iterator as = activeSessions.iterator();
							while (as.hasNext()) {
								String sstr = "";
								ClientSession cs = (ClientSession) as.next();
								if(cs.allPoints !=0 && cs.allPoints < 21){
									max = cs.allPoints;
									winnerName = cs.getName();
								}
								sstr += cs.getName() + " ";
								sstr += "all ";

								for(int y = 0; y < cs.cards.size(); y++)sstr += cs.cards.get(y) + " ";
								outQueue.addMessage(sstr);	
							}
						}
						outQueue.addMessage("The winner is: " + winnerName + " with " + max + " points. Congratulations!!");	
						beginning();
					}
					if (str == null) continue;
					String outMsg = getName() + " lausub: " + str;
					outQueue.addMessage(outMsg);
			} // while

			outQueue.addMessage(getName() + " lahkus...");
		} catch (IOException e) {
			outQueue.addMessage(getName() + " - avarii...");
		}

		try {
			socket.close();
		} catch (IOException e) {
		}

	}

	public  void sendMessage(String msg) {
		try {
			if (!socket.isClosed())
				netOut.println(msg);
			else
				throw new IOException(); // tegelikult: CALL catch()
		} catch (IOException eee) {
			outQueue.addMessage(getName() + " -avarii...");
			try {
				socket.close();
			} catch (IOException ee) {
			}
		}
	}

	@SuppressWarnings("unchecked")
	public Boolean checkGameOver(){
		boolean res = false;
		int temp = 0;
		Iterator activeSession = activeSessions.iterator();
		while (activeSession.hasNext()) {
			ClientSession clientSession = (ClientSession) activeSession.next();
			if(clientSession.ready > 0)temp++;
		}
		if(activeSessions.getAmountOfPlayers() <= temp)res = true;
		return res;
	}

	@SuppressWarnings("unchecked")
	public void beginning(){
		playerCards.addCards();

		synchronized (activeSessions) { // lukku!
			Iterator allSessions = activeSessions.iterator();
			while (allSessions.hasNext()) {
				ClientSession clientSession = (ClientSession) allSessions.next();
				if (!clientSession.isAlive()){
					clientSession.allPoints = 0;
					allSessions.remove();}
				else{
					clientSession.allPoints = 0;
					clientSession.ready = 0;
					clientSession.cards.clear();}
			}
		}
	}

}